/*
Hermes Core: General Purpose Mobile Agent Platform
Copyright (C) 2006 UNICAM - Università degli Studi di Camerino

Group leaders: Flavio Corradini and Emanuela Merelli

Developers: Ezio Bartocci, Diego Bonura, Rosario Culmone,
Davide Lorenzoli, Leonardo Mariani, Francesca Piersigilli, 
Lorenzo Scortichini, Leonardo Vito.

GNU Lesser Public License

This library is free software; you can redistribute it 
and/or modify it under the terms of the GNU Lesser General 
Public License as published by the Free Software Foundation, 
version 2.1 of the License.

This library is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU Library General Public License for more details.

You should have received a copy of the GNU Library General Public 
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.

Emanuela Merelli
Dipartimento di Matematica ed Informatica
Università di Camerino
via Madonna delle Carceri, 62032 Camerino, Italy
E.Mail: emanuela.merelli@unicam.it
*/
package hermesV2.core.starter;

import hermesV2.AgentThread;
import hermesV2.BasicServices;
import hermesV2.PlaceAddress;

import hermesV2.agent.Agent;
import hermesV2.agent.UserAgent;
import hermesV2.agent.Identificator;
import hermesV2.agent.ServiceAgent;

import hermesV2.core.id.Identify;
import hermesV2.core.id.Trace;

import java.util.Properties;


/**
 * It tries to start a new agent giving the Obj and the place address where try
 * to find new class file.
 *
 * @author Diego Bonura
 */
public class AgentStarter implements Starter {
   
    /**
     * Interface of the SendReceive component that manages the list of the
     * current agents running in the current place.
     */
    private Identify identify;

    /**
     * Interface of the SendReceive component that manages the list of the
     * current agents running in the current place.
     */
    private Trace trace;

    /** The current place address */
    private PlaceAddress currentPlaceAddress;

    /** The collector of every features presents into the place. */
    private BasicServices basicServices;

    

    /**The poperties object of the current place*/
    private Properties properties;

    /**
     * Creates a new <code>AgentStarter</code> object.
     *
     * 
     * @param currentPlaceAddress The Place address of the current platform.
     * @param properties The properties object of the current place.
     */
    public AgentStarter(PlaceAddress currentPlaceAddress, Properties properties) {
        this.currentPlaceAddress = currentPlaceAddress;
        this.properties = properties;
    }

    /**
     * Sets the Identify interface on the Id component.
     *
     * @param identify Th eIdentify interface of the Id component.
     */
    public void setIdentify(Identify identify) {
        this.identify = identify;
    }

    /**
     * Set the Trace interface of the Id component.
     *
     * @param trace The Trace interface of the Id component.
     */
    public void setTrace(Trace trace) {
        this.trace = trace;
    }

    /**
     * Stes the basicServices references into the component.
     *
     * @param basicServices The basicServices object from the place.
     */
    public void setBasicServices(BasicServices basicServices) {
        this.basicServices = basicServices;
    }

    /**
     * It starts the new obj using <code>AgentClassLoader</code>
     *
     * @param obj The obj migrated in the current place.
     * @param mode The way to start the agent, if it is the first execution of
     *        after a migration or after a clonation.
     * @param isServiceAgent True if the agent to start is a service False if it is an user agent.
     * @return True if the new obj is reloved, otherwise false.
     */
    public boolean startAgent(Object obj, int mode, boolean isServiceAgent) {
        //Setto i servizi utilizzabili dall'agente
        ((Agent) obj).setBasicServices(basicServices);

        Identificator id = null;

        switch (mode) {
        case Agent.INIT: {
            if (isServiceAgent) {
                id = identify.createNewServiceAgentIdentificator(((Agent) obj).getAgentName());
                ((ServiceAgent) obj).setPlaceProperties(properties);
            } else {
                id = identify.createNewUserAgentIdentificator(((Agent) obj).getAgentName());
            }

            ((Agent) obj).setIdentificator(id);

            AgentThread at = new AgentThread((Agent) obj, mode);
            identify.addAgentIdentificator(id, at);
            trace.addBornAgentIdentificator(id, currentPlaceAddress);
            at.start();

            break;
        }

        case UserAgent.RESTART: {
            AgentThread at = new AgentThread((Agent) obj, mode);
            identify.addAgentIdentificator(((Agent) obj).getIdentificator(), at);
            
            at.start();

            break;
        }

        case UserAgent.CLONE: {
            id = identify.createNewUserAgentIdentificator(((Agent) obj).getAgentName());
            ((Agent) obj).setIdentificator(id);
            AgentThread at = new AgentThread((Agent) obj, mode);
            identify.addAgentIdentificator(id, at);
            trace.addBornAgentIdentificator(id, currentPlaceAddress);
            at.start();
            break;
        }
        }

        return true;
    }
}
